Cloudflare WARPのネットワーク
マジ?と思うなら curl ifconfig.coしてみよう
何やら変なことをやっていそうなので,調べてみることにした
IPv4は172.16.0.2が必ず割り振られているように見える IPv6にはユニークローカルアドレスが1つ割り振られる このことから,たとえIPv6であってもNAPTを経由して外に出ているのではないか?という推論が得られる STUNを使ってローカル・グローバル間でのアドレス・ポートのマッピングを調べる なんでそんなことするの?と思ってしまうが
世界中で同じコンフィグで接続できるようにすることを考えると割り当てたアドレスからそのままインターネットに出られるみたいなのは現実的ではないかもしれない
一般的なNAPTではwell-knownなポートを使うのを避けようとして小さなポート番号に対して大きなポート番号をマッピングするのでそれを期待して次のようにやる: $ stunclient --family 6 --localport 2000 stun.l.google.com 19302
code:stun.l.google.com
Binding test: success
Local address: fd01:5ca1:ab1e:8569:ae1c:c772:8ad9:5d62.2000
Mapped address: 2a09:bac0:22::825:2bde.37886
ということで外に出るときにNAPTしていることがわかる ではなぜこのような現象が起きているのか?
この場合網内のルーティングをどうするのという問題が出てくる
ルーティングの識別子を WireGuard のヘッダに埋め込むといった興味深い話があるが,送信元 IP アドレスはコネクションの判別の役に立たないという部分が重要そう 識別子がなくとも動作するので,NAPT 自体は別の値を送信元 IP の代わりとなる識別子として使っていると考えるのが自然そう
ルーティングが正しければreceiver_indexで識別できるのか?
この下妄想
この状態でどのように網内のルーティングを行うのかという話だが,WireGuardのパケットの送信元IP(つまり,真のクライアントIPアドレス)を用いているのではないか? 実現方法はいろいろ想像できると思うが,一つ例を考えてみる
外向きならばクライアントのアドレスを使ってNAPTを通して外に出し 内向きならばsrcをクライアントのアドレスにしてネットワークに投げる
何かしらの理由で内部のL7LBはIPアドレスを隠せないようになっていると考えるのが自然だし,そうなっているとしたら↑のような構成になっているんじゃないか
反論一覧
これだとするとプライベートネットワークのIPアドレスを使うようにNAPTしてから内側に投げればいいんじゃないですか? Cloudflare WARPって移動しても接続が切れないようになっていたはずだけど,この方法だとIPアドレスが変化したタイミングで全てが変わってしまいませんか? HTTPを使ってCloudflare網外と通信しながら接続先を切り替えたところ,WARPの再接続の後コネクションは切れることなく1秒程度で再び通信するようになった Private Keyか何かを使って接続先を識別しつつNAPTテーブルのエントリを書き変えるみたいなことをしてそう メモ
$ stunclient --family 6 --localport 2000 stun2.l.google.com 19302
code:stun2.l.google.com
Binding test: success
Local address: fd01:5ca1:ab1e:8569:ae1c:c772:8ad9:5d62.2000
Mapped address: 2a09:bac0:22::825:2bde.37886
一種のCGNであるが,アドレス共有が行われているかどうかまでは分からなかった これらのポートで必ず異なるポートにマッピングされるのは0-9023までのようだ